<script setup lang="ts">
import { ref, watch, defineProps, onMounted } from "vue";
import { debounce } from '@/utils'
let masonry_wrap_width = <any>ref()

let masonry_data = <any>[]

let rankArr: any[] = []

// 获取行数 - 如果宽度为0（未设置）时才生效
const getColCount = () => {
    if (props.colWidth === 0) {
        return props.columns
    }
    // 四舍五入
    return Math.round(masonry_wrap_width / props.colWidth)
}

// 数据转换
const dataTransfer = (data: any, refresh = false) => {
    const width = getColWigth()
    let fragment = document.createDocumentFragment();
    data.forEach((item: any, _index: any) => {
        let percentage = item.imgw / item.imgh
        item.imageWidth = width
        item.imageHeight = width / percentage
        item.width = width
        let title_lines = Math.ceil(item.titleWidth / (width - props.contentPadding * 2))
        title_lines = title_lines > 2 ? 2 : title_lines
        item.height = Math.round((item.imageHeight + props.contentPadding * 2 + props.footerHeight + 23 * title_lines) * 1000) / 1000
        const r = rankc(item.height + props.gap)
        item.translatex = r.index * (width + props.gap)
        item.translatey = r.value

        let el = createEl('figure', `height:${item.height}px;width:${item.width}px;transform:translate(${item.translatex}px,${item.translatey}px)`);
        el.className = 'masonry-item'
        el.appendChild(createImgEl(item.img))

        let footer_el = createEl('div', ``)
        footer_el.className = 'item-footer'

        let title = createEl('div', ``, item.title)
        title.style.height = "auto"
        title.className = 'item-title'
        footer_el.appendChild(title)

        const author_el = createEl('div', ``, '@ 作者 · 10月28日')
        author_el.className = 'item-author'
        footer_el.appendChild(author_el)

        el.appendChild(footer_el)

        fragment.appendChild(el);
        // 添加 html
    })
    let dom: any = document.getElementById('masonry-wrap')
    dom.style.height = (Math.max.apply(null, rankArr)) + 'px'
    dom?.append(fragment)
    if (!refresh) masonry_data = masonry_data.concat(data)
    return data;
}
const createEl = (tag: string, styles: string = '', inderText = '') => {
    let el = document.createElement(tag)
    if (styles) el.style.cssText = styles
    if (inderText) { el.innerText = inderText }
    return el
}
const createImgEl = (src: string = '') => {
    let el = document.createElement('img')
    el.className = "item-img"
    if (src != '') {
        el.src = src
    }
    return el;
}
const rankc = (n: number) => {
    const index = rankArr.indexOf(Math.min.apply(null, rankArr))
    const res = { index: index, value: rankArr[index] }
    rankArr[index] = rankArr[index] + n
    return res
}

// 获取标题占用的宽度
const setTitleWidth = (data: any) => {
    let canvas = document.createElement('canvas');
    let context: any = canvas.getContext('2d');
    context.font = '15px Inter, Avenir, Helvetica, Arial, sans-serif';
    return data.map((item: { [x: string]: string; titleWidth: any; }) => {
        item.titleWidth = context.measureText(item.title).width
        return item
    })
}

// 获取单行宽度（已减去间距）
const getColWigth = () => {
    const count = getColCount();
    return Math.round(((masonry_wrap_width - (count - 1) * props.gap) / count) * 1000) / 1000
}

interface Props {
    columns?: (number), // 行数
    gap?: (number), // 间距
    data: object // 数据
    colWidth?: (number),
    contentPadding?: (number),
    footerHeight?: (number),
    eid: (string),
    appends: object
}

const props = withDefaults(defineProps<Props>(), {
    columns: 4,
    data: <any>{},
    colWidth: 0,
    gap: 15,
    contentPadding: 12,
    footerHeight: 24,
    eid: '',
    appends: <any>{}
})
watch(
    () => props.data, (_newval, _oldval) => {
       
        rankArr = Array(getColCount()).fill(0)
        const data = setTitleWidth(props.data)
        dataTransfer(data)
    }
)
watch(
    () => props.appends, (_newval) => {
        const data = setTitleWidth(_newval)
        //    console.log(data)
        dataTransfer(data)
    }
)


const emit = defineEmits<{
    loadmore: []
}>()

const relayout = debounce(function () {
    let dom: any = document.getElementById('masonry-wrap')
    if(!dom){
        return 
    }
    masonry_wrap_width = dom.offsetWidth
    rankArr = Array(getColCount()).fill(0)
    dom.innerHTML = ''
    dataTransfer(masonry_data, true)
}, 300)

onMounted(() => {
    masonry_wrap_width = document.getElementById('masonry-wrap')?.offsetWidth ?? 0
    const dom = document.getElementById(props.eid)
    
    dom?.addEventListener('scroll', function (e) {
        const target: any = e.target
        if (target.scrollHeight < target.scrollTop + target.offsetHeight + 50) {
            emit('loadmore')
            
        }
    })
    window.addEventListener('resize', relayout)
});

</script>
<template>
    <div id="masonry-wrap"></div>
</template>
<style>
#masonry-wrap {
    position: relative;
    box-sizing: content-box;
}

.masonry-item {
    display: flex;
    justify-content: flex-end;
    flex-direction: column;
    border-radius: .5rem;
    background-color: var(--color-bg-b1);
    position: absolute;
    overflow: hidden;
    cursor: pointer;
}

.item-img {
    width: 100%;
}

.item-title {
    height: 46px;
    word-break: break-all;
    text-overflow: ellipsis;
    -webkit-line-clamp: 2;
    color: #161823;
    color: var(--color-text-t1);
    cursor: pointer;
    -webkit-box-orient: vertical;
    font-size: 15px;
    line-height: 23px;
    display: -webkit-box;
    overflow: hidden;
}

.item-footer {
    width: 100%;
    flex-grow: 1;
    padding: 12px;
}

.item-author {
    color: #aaabaf;
    height: 23px;
    line-height: 23px;
    margin-top: 6px;
    font-size: 0.825rem;
}</style>